package com.flipdf2;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;

import javax.swing.Action;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class DocumentPanel extends JPanel {
	public static final int SINGLE_PAGE = 0;
	public static final int MULTI_PAGE = 1;

	public static final int GAP_WIDTH = 5;
	public static final int BOTTOM_WIDTH = 20;

	private boolean scrolled;
	private Document model;

	private float scale = 1.0f;

	private JComponent frame;

	public DocumentPanel(JComponent frame, Document model) {
		this.frame = frame;
		this.model = model;
		this.scrolled = false;
		update();
	}

	public Document getModel() {
		return this.model;
	}

	private void update() {
		this.setPreferredSize(calculateSize());
		this.frame.revalidate();
		this.repaint();
	}

	public void setShowType(int showType) {
		if (showType == SINGLE_PAGE) {
			scrolled = false;
		} else if (showType == MULTI_PAGE) {
			scrolled = true;
		}
		update();
		this.repaint();
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;

		if (model.getPageCount() == 0) {
			return;
		}

		g2.setColor(Color.GRAY);
		g2.fillRect(0, 0, this.getSize().width, this.getSize().height);

		g2.scale(scale, scale);

		if (!this.scrolled) {
			Page page = model.getPage(0);
			int currWidth = (int) this.getSize().getWidth();
			int x = 0;
			if (currWidth > page.getWidth() * scale) {
				x = (int) ((currWidth - page.getWidth() * scale) / 2);
			}
			g2.translate(x, 0);
			page.draw(g2);
		} else {
			int n = model.getPageCount();
			int x = 0, lastX = 0;
			int y = 0;
			int currWidth = (int) this.getSize().getWidth();
			for (int i = 0; i < n; i++) {
				Page page = model.getPage(i);
				if (currWidth > page.getWidth() * scale) {
					x = (int) ((currWidth - page.getWidth() * scale) / 2);
				}
				y = y + GAP_WIDTH;
				g2.translate(x - lastX, y);
				page.draw(g2);
				lastX = x;
				y = y + page.getHeight();
			}
		}
	}

	private Dimension calculateSize() {
		if (model.getPageCount() == 0) {
			return new Dimension(0, 0);
		}

		int width = 0;
		int height = 0;
		if (!this.scrolled) {
			Page page = model.getPage(0);
			width = (int) (page.getWidth() * scale) > this.getSize().width ? (int) (page.getWidth() * scale)
					: this.getSize().width;
			height = (int) (page.getHeight() * scale) > this.getSize().height ? (int) (page
					.getHeight() * scale) : this.getSize().height;
			return new Dimension(width, height);
		}

		width = 0;
		height = 0;
		int n = model.getPageCount();
		for (int i = 0; i < n; i++) {
			Page page = model.getPage(i);
			if (page.getWidth() > width) {
				width = page.getWidth();
			}
			height += page.getHeight();
			height += GAP_WIDTH;
		}
		height += BOTTOM_WIDTH;

		width = (int) (width * scale) > this.getSize().width ? (int) (width * scale) : this
				.getSize().width;
		height = (int) (height * scale) > this.getSize().height ? (int) (height * scale) : this
				.getSize().height;

		return new Dimension(width, height);
	}

	public Action getZoomAction() {
		return this.zoomAction;
	}

	private Action zoomAction = new Action() {

		public void addPropertyChangeListener(PropertyChangeListener listener) {
		}

		public Object getValue(String key) {
			return null;
		}

		public boolean isEnabled() {
			return false;
		}

		public void putValue(String key, Object value) {
		}

		public void removePropertyChangeListener(PropertyChangeListener listener) {
		}

		public void setEnabled(boolean b) {
		}

		public void actionPerformed(ActionEvent e) {
			Object obj = e.getSource();
			if (obj == null)
				return;
			if (obj instanceof JComboBox) {
				JComboBox comboBox = (JComboBox) obj;
				Object selObj = comboBox.getSelectedItem();
				if (selObj != null) {
					String selItem = (String) selObj;
					scale = Float.parseFloat(selItem) / 100;
					update();
				}
			}
		}
	};
}
